package com.fly.core.interceptor;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import lombok.extern.slf4j.Slf4j;

/**
 * 
 * 注解处理工具类
 * 
 * @author 00fly
 * @version [版本号, 2020-04-16]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
@Slf4j
public class AnnotationHelper
{
    private static List<String> cacheList = new ArrayList<>();
    
    private AnnotationHelper()
    {
        super();
    }
    
    /**
     * 得到类上面的注解信息
     * 
     * @param scannerClass
     * @param allowInjectClass
     * @return
     */
    private static Annotation getClassAnnotation(Class<?> scannerClass, Class<? extends Annotation> allowInjectClass)
    {
        if (!scannerClass.isAnnotationPresent(allowInjectClass))
        {
            return null;
        }
        return scannerClass.getAnnotation(allowInjectClass);
    }
    
    /**
     * 使用Java反射得到注解的信息
     * 
     * @param annotation
     * @param methodName
     * @return Exception
     */
    private static Object getAnnotationInfo(Annotation annotation, String methodName)
        throws Exception
    {
        if (annotation == null)
        {
            return null;
        }
        Method declaredMethod = annotation.getClass().getDeclaredMethod(methodName, null);
        return declaredMethod.invoke(annotation, null);
    }
    
    /**
     * 从上下文获取 Controller注解类的 RequestMapping注解url信息
     * 
     * @param applicationContext
     * @return
     * @throws Exception
     * @see [类、类#方法、类#成员]
     */
    public static List<String> getRequestMappingURL(ApplicationContext applicationContext)
        throws Exception
    {
        if (cacheList.isEmpty())
        {
            synchronized (AnnotationHelper.class)
            {
                // lambda
                applicationContext.getBeansWithAnnotation(Controller.class).values().stream().forEach(clazz -> collectUrls(clazz.getClass()));
            }
        }
        return cacheList;
    }
    
    /**
     * 获取Url
     * 
     * @param clazz
     */
    private static void collectUrls(Class<? extends Object> clazz)
    {
        try
        {
            Object object = getAnnotationInfo(getClassAnnotation(clazz, RequestMapping.class), "value");
            if (object != null)
            {
                Stream.of((String[])object).filter(it -> !it.contains("$")).forEach(it -> cacheList.add(it));
            }
        }
        catch (Exception e)
        {
            log.error(e.getMessage(), e);
        }
    }
}
